<template>
  <div class="menu">
    <div class="menu-left" ref="menuList">
      <ul>
        <li class="menu-item" v-for="(menu, index) in menus" :key="index" :class="{ current: index === currentIndex.value }" @click="clickList(index)">
          <p class="text">{{ menu.name }}</p>
        </li>
      </ul>
    </div>
    <div class="menu-right" ref="itemList">
      <ul>
        <li class="cate" v-for="(menu, index1) in menus" :key="index1">
          <h4 class="cate-title">{{ menu.name }}</h4>
          <ul class="cate-item">
            <li v-for="(item, index2) in menu.children" :key="index2">
              <router-link class="cate-item-wrapper" :to="{ name: 'goodslist', params:{ category_id: item.id } }">
                <div class="cate-item-img">
                  <img :src="item.picture" alt="">
                </div>
                <span>{{ item.name }}</span>
              </router-link>
            </li>
          </ul>
        </li>
        <li class="cate-bottom"></li>
      </ul>
    </div>
  </div>
</template>
<script setup>
import { onMounted, watch, nextTick, ref, computed } from 'vue'
import { getCategoryList } from '../api'
import BScroll from '@better-scroll/core'

const menus = ref([])
const rightLiTops = ref([])
const itemList = ref()
const scrollY = ref(0)
let leftBscroll = null
let rightBscroll = null
const menuList = ref(null)
const currentIndex = ref(-1)

onMounted(() => {
  loadCategoryList()
  RightHeightFix()
})

watch(menus, () => {
  nextTick(() => {
    initRightHeight()
    initBScroll()
  })
})

const loadCategoryList = async () => {
  let data = await getCategoryList()
  const treeData = convertToTree(data)
  menus.value = treeData
}

const convertToTree = data => {
  const treeData = []
  const map = {}
  for (const item of data) {
    map[item.id] = { ...item, children: [] }
  }
  for (const item of data) {
    const node = map[item.id]
    if (item.pid === 0) {
      treeData.push(node)
    } else {
      const parent = map[item.pid]
      if (parent) {
        if (!parent.children) {
          parent.children = []
        }
        parent.children.push(node)
      }
    }
  }
  return treeData
}

const clickList = index => {
  scrollY.value = rightLiTops.value[index]
  rightBscroll.scrollTo(0, -scrollY.value, 300)
  initLeftScroll(index)
}

const initRightHeight = () => {
  const itemArray = [0]
  const allList = itemList.value?.getElementsByClassName('cate')
  Array.from(allList).forEach(li => {
    itemArray.push(li.offsetTop + li.clientHeight)
  })
  rightLiTops.value = itemArray
}

const initBScroll = () => {
  leftBscroll = new BScroll(menuList.value, {
    click: true,
    mouseWheel: true,
    bounce: false
  })
  rightBscroll = new BScroll(itemList.value, {
    click: true,
    mouseWheel: true,
    probeType: 3,
    bounce: false
  })
  rightBscroll.on('scroll', pos => {
    scrollY.value = Math.abs(pos.y)
    currentIndex.value = computeCurrentIndex()
  })
}

const RightHeightFix = () => {
  let bottom = itemList.value?.getElementsByClassName('cate-bottom')[0]
  if (bottom) {
    bottom.style.height = itemList.value?.clientHeight / 1.2 + 'px'
  }
}

const initLeftScroll = index => {
  const menu = menuList.value?.querySelectorAll('.menu-item')
  if (menu && menu.length > index) {
    let el = menu[index]
    leftBscroll.scrollToElement(el, 300, 0, -100)
  }
}

const computeCurrentIndex = () => {
  if (!rightLiTops.value || !rightLiTops.value.length) return -1

  const lastIndex = rightLiTops.value.length - 2
  for (let i = 0; i < lastIndex; i++) {
    if (scrollY.value >= rightLiTops.value[i] && scrollY.value < rightLiTops.value[i + 1]) {
      initLeftScroll(i)
      return i
    }
  }

  if (scrollY.value >= rightLiTops.value[lastIndex]) {
    initLeftScroll(lastIndex)
    return lastIndex
  }

  return -1
}

watch(scrollY, () => {
  currentIndex.value = computeCurrentIndex()
})
</script>
<style lang="less" scoped>
ul {
  margin: 0;
  padding: 0;
}
li {
  list-style: none;
}
.menu {
  display: flex;
  position: absolute;
  text-align: center;
  top: 46px;
  bottom: 50px;
  width: 100%;
  overflow: hidden;
  font-family: 'Roboto', sans-serif;

  .menu-left {
    flex: 0 0 90px;
    width: 90px;
    background: #f8f9fa;
    line-height: 54px;
    transition: background 0.3s ease;

    .menu-item {
      height: 54px;
      width: 100%;
      border-bottom: 1px solid #e1e1e1;
      cursor: pointer;
      transition: background 0.3s ease;

      .text {
        width: 100%;
        margin: 0;
        font-size: 14px;
        color: #6c757d;
        transition: color 0.3s ease;
      }

      &:hover {
        background: #e9ecef;
        .text {
          color: #007bff;
        }
      }
    }

    .current {
      background: #007bff;
      .text {
        color: #fff;
      }
    }
  }

  .menu-right {
    flex: 1;
    background: #fff;

    .cate {
      .cate-title {
        margin: 0;
        text-align: left;
        font-size: 16px;
        color: #333;
        font-weight: 500;
        padding: 10px;
        border-bottom: 1px solid #e1e1e1;
      }

      .cate-item {
        padding: 10px;
        display: flex;
        flex-wrap: wrap;

        li {
          width: 33.3333%;
          padding: 5px;
          box-sizing: border-box;

          .cate-item-wrapper {
            display: flex;
            flex-direction: column;
            align-items: center;
            text-align: center;

            .cate-item-img {
              width: 70px;
              height: 70px;
              margin-bottom: 5px;

              img {
                width: 100%;
                height: 100%;
                object-fit: cover;
              }
            }

            span {
              font-size: 14px;
              color: #6c757d;
              transition: color 0.3s ease;

              &:hover {
                color: #007bff;
              }
            }
          }
        }
      }
    }
  }
}
</style>